﻿using Renci.SshNet;
using Renci.SshNet.Sftp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SimpleTerminal
{
    public partial class SftpExplorer : UserControl
    {
        SftpClient sftpClient;
        public SftpExplorer()
        {
            InitializeComponent();
            this.listView1.Columns.Add("名字", 240, HorizontalAlignment.Left);
            this.listView1.Columns.Add("大小", 120, HorizontalAlignment.Left);
            this.listView1.Columns.Add("日期", 160, HorizontalAlignment.Left);
            this.listView1.Columns.Add("权限", 120, HorizontalAlignment.Left);

            this.listView1.MouseDoubleClick += Explorer_MouseDoubleClick;
            // Browse(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
           // sftpClient = new SftpClient("192.168.3.97", 22, "code", "code");
           // sftpClient.Connect();
           // BeginBrowse(sftpClient.WorkingDirectory);
        }

        private void Explorer_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ListViewHitTestInfo hitTestInfo = listView1.HitTest(e.X, e.Y);
            if (hitTestInfo.Item == null || hitTestInfo.Item.Tag == null)
                return;
            File fileinfo = hitTestInfo.Item.Tag as File;
            if (fileinfo.Type == FileTyle.Directory)
            {
                BeginBrowse(fileinfo.FullName);
            }
            //Console.WriteLine(fileinfo.FullName);
        }

        private void BeginBrowse(string path)
        {
            Thread thread = new Thread((ThreadStart)delegate
            {
                FilesCollection fileinfos = GetRemotelist(path);
                this.Invoke(new Action(() =>
                {
                    remotePath.Text = sftpClient.GetCanonicalPath(path);
                    Browse(fileinfos);
                }));
            })
            {
                IsBackground = true
            };
            thread.Start();
        }

        private FilesCollection GetRemotelist(string path)
        {

            FilesCollection fileinfos = new FilesCollection();
           // sftpClient.
            foreach (SftpFile sftpFile in sftpClient.ListDirectory(path))
            {
                File file = new File
                {
                    FullName = sftpFile.FullName,
                    Name = sftpFile.Name,
                    Size = sftpFile.Length,
                //    Owner = sftpFile.,
                    OwnerCanRead = sftpFile.OwnerCanRead,
                    OwnerCanWrite = sftpFile.OthersCanWrite,
                    OwnerCanExecute = sftpFile.OwnerCanExecute,
                    GroupCanRead = sftpFile.GroupCanRead,
                    GroupCanWrite = sftpFile.GroupCanWrite,
                    GroupCanExecute = sftpFile.GroupCanExecute,
                    OthersCanRead = sftpFile.OthersCanRead,
                    OthersCanWrite = sftpFile.OthersCanWrite,
                    OthersCanExecute = sftpFile.OwnerCanExecute,
                    DateTime = sftpFile.LastWriteTime
                };
                if (sftpFile.Name == "..")
                {
                    //if (!path.EndsWith("/"))
                    //{
                    //    path =
                    //}
                    //file.FullName = ;
                    file.Type = FileTyle.Directory;
                    fileinfos.Navigation.Add(file);
                }
                else if (sftpFile.Name == ".")
                {
                    file.Type = FileTyle.Directory;
                    fileinfos.Navigation.Add(file);
                }
                else if (sftpFile.IsDirectory)
                {
                    file.Type = FileTyle.Directory;
                    fileinfos.Directorys.Add(file);
                }
                else
                {
                    file.Type = FileTyle.File;
                    fileinfos.Files.Add(file);
                }
            }
            return fileinfos;
        }

        private void Browse(FilesCollection fileinfos)
        {
            this.listView1.Items.Clear();
            this.listView1.BeginUpdate();
            this.ShownList(fileinfos.Navigation);
            this.ShownList(fileinfos.Directorys);
            this.ShownList(fileinfos.Files);
            this.listView1.EndUpdate();
        }

        private void ShownList(List<File> lists)
        {
            foreach (File fileinfo in lists)
            {
                int imageIcon = 0;
                switch (fileinfo.Type)
                {
                    case FileTyle.Directory:
                        imageIcon = 0;
                        break;
                    case FileTyle.File:
                        imageIcon = 1;
                        break;
                    default:
                        imageIcon = 0;
                        break;
                }
                ListViewItem lvi = new ListViewItem
                {
                    Text = fileinfo.Name,
                    ImageIndex = imageIcon,
                    Tag = fileinfo
                };
                lvi.SubItems.Add(fileinfo.Size.ToString());
                lvi.SubItems.Add(fileinfo.DateTime.ToString());
                lvi.SubItems.Add(fileinfo.Permissions);
                this.listView1.Items.Add(lvi);
            }
        }

        enum FileTyle
        {
            Parent,
            Directory,
            File
        }
        class File
        {
            public string FullName;
            public string Name;
            public long Size;
            public FileTyle Type;
            public DateTime DateTime;
            public string Owner = "";
            public bool OwnerCanRead = false;
            public bool OwnerCanWrite = false;
            public bool OwnerCanExecute = false;
            public bool GroupCanRead = false;
            public bool GroupCanWrite = false;
            public bool GroupCanExecute = false;
            public bool OthersCanRead = false;
            public bool OthersCanWrite = false;
            public bool OthersCanExecute = false;
            public string Permissions
            {
                get
                {
                    return "" +
                        (OwnerCanRead ? "r" : "-") +
                        (OwnerCanWrite ? "w" : "-") +
                        (OwnerCanExecute ? "x" : "-") +
                        (GroupCanRead ? "r" : "-") +
                        (GroupCanWrite ? "w" : "-") +
                        (GroupCanExecute ? "x" : "-") +
                        (OthersCanRead ? "r" : "-") +
                        (OthersCanWrite ? "w" : "-") +
                        (OthersCanExecute ? "x" : "-")
                        ;
                }
            }

        }
        class FilesCollection
        {
            public List<File> Navigation = new List<File>();
            public List<File> Directorys = new List<File>();
            public List<File> Files = new List<File>();
        }


        private FilesCollection Getlist(string path)
        {
            FilesCollection fileinfos = new FilesCollection();

            if (Directory.GetDirectoryRoot(path) != path)
            {
                fileinfos.Directorys.Add(new File
                {
                    FullName = Directory.GetParent(path).FullName,
                    Name = "..",
                    Size = 0,
                    Type = FileTyle.Directory,
                    DateTime = Directory.GetParent(path).LastAccessTime
                });

            }

            foreach (string filename in Directory.GetFileSystemEntries(path))
            {
                //if(item.)
                FileInfo fileInfo = new FileInfo(filename);
                if ((fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
                    continue;

                if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
                {
                    File file = new File
                    {
                        FullName = fileInfo.FullName,
                        Name = fileInfo.Name,
                        Size = 0,
                        Type = FileTyle.Directory,

                        DateTime = fileInfo.LastWriteTime
                    };
                    fileinfos.Directorys.Add(file);
                }
                else
                {
                    File file = new File
                    {
                        FullName = fileInfo.FullName,
                        Name = fileInfo.Name,
                        Size = fileInfo.Length,
                        Type = FileTyle.File,
                        DateTime = fileInfo.LastWriteTime
                    };
                    fileinfos.Files.Add(file);
                }

            }/*
            foreach (var item in directory.GetFiles())
            {
                FileInfo fileInfo = new FileInfo(item.FullName);

                Fileinfo fileinfo = new Fileinfo
                {
                    Name = item.Name,
                    FullName = item.FullName,
                    Size = fileInfo.Length,
                    Type = FileTyle.File,
                    DateTime = item.LastWriteTime
                };

                fileinfos.files.Add(fileinfo);
            }*/
            return fileinfos;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
        }
    }
}
